A debugger is a computer program used to detect and correct errors in a target computer program. Most debuggers have a feature that allows a user to stop execution of the target computer program and analyze variables in the program. A user may stop execution of the program by setting a breakpoint at a desired location in the program and allowing the program to run up to the breakpoint.
Typically, a debugger will implement a software breakpoint through an opcode replacement, through which the opcode of an instruction may be replaced with an invalid opcode or an opcode specifically designated as a breakpoint opcode. When the program runs and the debugger encounters the breakpoint, the invalid or breakpoint opcode may cause an exception. The debugger gains control of the program, handles the exception, and stops execution of the program until a user resumes the program. When the breakpoint is removed, the displaced opcode is replaced.
When a user sets a breakpoint on a line of source code, the debugger creates the breakpoint at the beginning of the first statement associated with the source line. When program execution comes to the breakpoint, the breakpoint fires and program execution halts before any statements on the source line are executed. A line of source code may contain multiple statements, with each statement corresponding to one or more machine instructions generated by the compiler. When the compiler generates debuggable code for the debugger, as opposed to optimized code, it does so that the debugger can stop at statement boundaries and retrieve variables. If the debugger was to stop in the middle of a statement, the variable value may not be accurate, as the statement would not be executed through the machine instructions associated with that statement, and variable values may reside in registers and temporary memory locations. When a breakpoint is set on a statement, it is set on the first instruction associated with the statement.